//
//  CLStatistics.m
//  ABAuthModule
//
//  Created by Leo on 2019/4/3.
//

#import "CLStatistics.h"
#import "Aspects.h"

// 通用key
NSString const *ABCollecterTargetKey       = @"target";         // 响应被hook的类
NSString const *ABCollecterDescKey         = @"desc";           // 统计值描述

// 页面访问统计key
NSString const *ABCollecterVCsKey          = @"pageEvents";     // 页面访问事件Key
NSString const *ABCollecterSelectorKey     = @"selector";       // 被hook的selector
NSString const *ABCollecterEntrySelectorKey= @"entrySelector";  // hook viewWillAppear:
NSString const *ABCollecterLoadSelectorKey = @"loadSelector";   // hook viewDidLoad
NSString const *ABCollecterOffSelectorKey  = @"offSelector";    // hook viewWillDisapper:
NSString const *ABCollecterUVCodeKey       = @"uvCode";         // 页面UV统计码

// 点击统计码以及码值key
NSString const *ABCollecterEventsKey       = @"clickEvents";    // 同一事件不同操作的统计事件Key
NSString const *ABCollecterUserEventsKey   = @"userEvents";     // 基于用户维度的统计事件Key
NSString const *ABCollecterCodeKey         = @"code";           // 统计码
NSString const *ABCollecterCodeValueKey    = @"codeValue";      // 统计码值

@interface CLStatistics ()

@property (nonatomic,strong) NSArray *collectVCArray;           // 页面统计事件
@property (nonatomic,strong) NSArray *collectEventArray;        // 同一事件不同操作的统计事件
@property (nonatomic,strong) NSArray *collectUserEventArray;    // 基于用户维度的统计事件

@end

@implementation CLStatistics

SINGLETON_CL_IMPLEMENT(CLStatistics)

+ (void)startStatistics {
    [self configureDataWithPlistFile:@"CLHooker"];
}

/**
 读取plist文件
 遍历文件里的所有类别，在对应方法中注入统计代码
 
 @param plistFileName plist文件名
 */
+ (void)configureDataWithPlistFile:(NSString *)plistFileName{
    NSString *path = [[NSBundle mainBundle] pathForResource:plistFileName ofType:@"plist"];
    NSDictionary *dic = [NSDictionary dictionaryWithContentsOfFile:path];
    [CLStatistics sharedInstance].collectVCArray = [dic objectForKey:ABCollecterVCsKey];
    [CLStatistics sharedInstance].collectEventArray = [dic objectForKey:ABCollecterEventsKey];
    [CLStatistics sharedInstance].collectUserEventArray = [dic objectForKey:ABCollecterUserEventsKey];
    // 页面访问
    if ([CLStatistics sharedInstance].collectVCArray.count) {
        [self configPV];
    }
    // 点击事件
    if ([CLStatistics sharedInstance].collectEventArray.count) {
        [self configEvents];
    }
    // 基于用户Id的点击事件
    if ([CLStatistics sharedInstance].collectUserEventArray.count) {
        [self configUserEvents];
    }
}

+ (void)configPV {
    [[CLStatistics sharedInstance].collectVCArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:[NSDictionary class]]) {
            [self configPageEventWithDictionary:obj options:AspectPositionAfter];
        };
    }];
}

+ (void)configEvents {
    [[CLStatistics sharedInstance].collectEventArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:[NSDictionary class]]) {
            [self configEventWithDictionary:obj options:AspectPositionBefore];
        }
    }];
}

+ (void)configUserEvents {
    [[CLStatistics sharedInstance].collectUserEventArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:[NSDictionary class]]) {
            [self configUserEventWithDictionary:obj options:AspectPositionBefore];
        }
    }];
}

+ (void)configPageEventWithDictionary:(NSDictionary *)dic options:(AspectOptions)option {
    
    NSString *targetClass = dic[ABCollecterTargetKey];
    NSString *entrySelectorName = dic[ABCollecterEntrySelectorKey];
    NSString *offSelectorName = dic[ABCollecterOffSelectorKey];
    NSString *loadSelectorName = dic[ABCollecterLoadSelectorKey];
    NSString *uvCode = dic[ABCollecterUVCodeKey];
    NSString *pageDesc = dic[ABCollecterDescKey];
    
    Class target = NSClassFromString(targetClass);
    // viewWillAppear: 统计
    if (entrySelectorName.length && target) {
        SEL selector = NSSelectorFromString(entrySelectorName);
        [target aspect_hookSelector:selector withOptions:option usingBlock:^(id<AspectInfo> info) {
            NSString *className = NSStringFromClass([[info instance] class]);
            [CLStatistics logWithTarget:targetClass selector:entrySelectorName pageDesc:pageDesc];
        } error:NULL];
    }
    // viewWillDisappear: 统计
    if (offSelectorName.length && target) {
        SEL selector = NSSelectorFromString(offSelectorName);
        [target aspect_hookSelector:selector withOptions:option usingBlock:^(id<AspectInfo> info) {
            NSString *className = NSStringFromClass([[info instance] class]);
            [CLStatistics logWithTarget:targetClass selector:offSelectorName pageDesc:pageDesc];
        } error:NULL];
    }
    
    // viewDidload 统计
    if (loadSelectorName.length && uvCode.length && target) {
        SEL selector = NSSelectorFromString(loadSelectorName);
        [target aspect_hookSelector:selector withOptions:option usingBlock:^(id<AspectInfo> info){
            NSString *className = NSStringFromClass([[info instance] class]);
            [CLStatistics logWithTarget:className selector:loadSelectorName code:uvCode codeDesc:pageDesc];
        } error:NULL];
    }
}

+ (void)configUserEventWithDictionary:(NSDictionary *)dic options:(AspectOptions)option {
    NSString *targetClass = dic[ABCollecterTargetKey];
    NSString *selectorName = dic[ABCollecterSelectorKey];
    NSString *code = dic[ABCollecterCodeKey];
    NSString *codeDesc = dic[ABCollecterDescKey];
    
    Class target = NSClassFromString(targetClass);
    
    if (selectorName.length && target) {
        SEL selector = NSSelectorFromString(selectorName);
        [target aspect_hookSelector:selector withOptions:option usingBlock:^{
            [CLStatistics logWithTarget:targetClass selector:selectorName code:code codeDesc:codeDesc];
        } error:NULL];
    }
}

+ (void)configEventWithDictionary:(NSDictionary *)dic options:(AspectOptions)option {
    NSString *targetClass = dic[ABCollecterTargetKey];
    NSString *selectorName = dic[ABCollecterSelectorKey];
    NSString *code = dic[ABCollecterCodeKey];
    NSString *codeValue = dic[ABCollecterCodeValueKey];
    NSString *codeDesc = dic[ABCollecterDescKey];
    
    Class target = NSClassFromString(targetClass);
    
    if (selectorName.length && target) {
        SEL selector = NSSelectorFromString(selectorName);
        [target aspect_hookSelector:selector withOptions:option usingBlock:^{
            [CLStatistics logWithTarget:targetClass selector:selectorName code:code codeDesc:codeDesc];
        } error:NULL];
    }
}

+ (void)logWithTarget:(NSString *)target selector:(NSString *)selector pageDesc:(NSString *)desc {
    NSLog(@"\n@*************************************************@\n当前统计描述：：：%@\n当前类名称：：：%@\n方法名为：：：%@\n@*************************************************@",desc,target,selector);
}

+ (void)logWithTarget:(NSString *)target selector:(NSString *)selector code:(NSString *)code codeDesc:(NSString *)desc {
     NSLog(@"\n@##################################################@\n当前统计描述：：：%@\n当前类名称：：：%@\n统计码为：：：%@\n方法名为：：：%@\n@##################################################@",desc,target,code,selector);
}

@end
